package lion.dev.lang;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 面象切面的对象代理类，通常叫作AOP,该类通过cglib来实现代理功能，<br/>
 * 如果代理的是一个类，那么对该类的所有方法调用都会进行拦截， 即使是本类方法调用本类自身的方法。<br/>
 * 如果代理的是一个对象， 那么只会对该对象方法调用时只进行一次方法拦截，如对象中的方法再调用了本对象的方法，只会在开始调用时拦截一次。
 * 
 * <pre>
 * time   2013年10月12日
 * mail   hl_0074@sina.com
 * </pre>
 * 
 * @author lion
 */
public class Proxy implements MethodInterceptor {

	private Object target;
	private Interceptor interceptor;

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

		// begin

		Object self = target == null ? obj : target;
		Object result = null;

		try {

			boolean b = interceptor.onBefore(self, method, args);
			if (!b) { return result; }

			if (this.target != null) {
				result = method.invoke(this.target, args);
			} else {
				result = proxy.invokeSuper(obj, args);
			}
		} catch (Throwable e) {
			interceptor.onException(self, method, e, args);
		} finally {
			interceptor.onPost(self, method, args);
		}

		return result;
	}

	/**
	 * proxy a object
	 */
	@SuppressWarnings("unchecked")
	public static <T> T proxy(T target, Interceptor interceptor) {

		Proxy proxy = new Proxy();
		proxy.target = target;
		return proxy((Class<T>) target.getClass(), proxy, interceptor);
	}

	/**
	 * proxy a class，will intercept every declared method in the class
	 */
	public static <T> T proxy(Class<T> clazz, Interceptor interceptor) {

		Proxy proxy = new Proxy();
		return proxy(clazz, proxy, interceptor);
	}

	@SuppressWarnings("unchecked")
	private static <T> T proxy(Class<T> clazz, Proxy proxy, Interceptor interceptor) {

		proxy.interceptor = interceptor;

		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(clazz);
		enhancer.setCallback(proxy);
		return (T) enhancer.create();
	}

}
